package com.codedef.config;


import com.codedef.common.exception.CustomException;
import com.codedef.common.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;


@Slf4j
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {

    public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
                                ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }


    @Override
    protected Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions errorAttributeOptions) {
        log.error("getErrorAttributes 2");
        int code = HttpStatus.INTERNAL_SERVER_ERROR.value();
        Throwable exception = super.getError(request);
        System.out.println(exception);

        /* 用于返回给前端的Map */
        Map<String, Object> map = new HashMap<>();
        map.put("data", null);

        /* 如果是CustomException，注入自定义的返回消息 */
        if (exception instanceof CustomException) {
            CustomException customException = (CustomException) exception;
            map.put( "code", customException.getResultCode().code() );
            map.put( "message", customException.getResultCode().message() + 'G');
        } else {  // 其他异常统一返回
            map.put("code", ResultCode.SYSTEM_INNER_ERROR.code());
            map.put("message", ResultCode.SYSTEM_INNER_ERROR.message() + 'G');
        }

        return map;
    }


    /**
     * 指定响应处理方法为JSON处理的方法
     * @param errorAttributes
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        log.error("getRoutingFunction");
        return RouterFunctions.route(RequestPredicates.all(), this::myRenderErrorResponse);
    }


    /**
     * 根据code获取对应的HttpStatus
     * @param errorAttributes
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        log.error("getHttpStatus");
//        int statusCode = (int) errorAttributes.get("code");
        return 200;
    }


    protected Mono<ServerResponse> myRenderErrorResponse(ServerRequest request) {
        log.debug("进入Gateway的myRenderErrorResponse方法");
        Map<String, Object> map = this.getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
        return ServerResponse.status(200).contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(map));
    }
}